/*
 * ZFreq by CyrIng
 *
 * Copyright (C) 2014 CYRIL INGENIERIE
 * Licenses: GPL2
 */

#define	_MAX_CPU_ 64

#define	SHM_DEVNAME "zfreq_ring0"
#define	SHM_FILENAME "/dev/"SHM_DEVNAME

#define	ZF_IA32_TIME_STAMP_COUNTER	0x10
#define	ZF_IA32_PERF_STATUS		0x198
#define	ZF_IA32_THERM_STATUS		0x19c
#define	ZF_IA32_FIXED_CTR1		0x30a
#define	ZF_IA32_FIXED_CTR2		0x30b
#define	ZF_IA32_FIXED_CTR_CTRL		0x38d
#define	ZF_IA32_PERF_GLOBAL_CTRL 	0x38f

#define	ZF_MSR_PLATFORM_INFO		0xce
#define	ZF_MSR_TURBO_RATIO_LIMIT	0x1ad

#define	ZF_MSR_CORE_C3_RESIDENCY	0x3fc
#define	ZF_MSR_CORE_C6_RESIDENCY	0x3fd

#define	ZF_MSR_TEMPERATURE_TARGET	0x1a2
/*
#define	SMBIOS_PROCINFO_STRUCTURE	4
#define	SMBIOS_PROCINFO_INSTANCE	0
#define	SMBIOS_PROCINFO_EXTCLK		0x12
#define	SMBIOS_PROCINFO_THREADS		0x25
*/
#define	ARCHITECTURES 7
//	[Nehalem]
#define	Nehalem				0
#define	Nehalem_CPUID_SIGNATURE		{ExtFamily:0x0, Family:0x6, ExtModel:0x1, Model:0xA}
#define	Nehalem_BASE_CLOCK		133
//	[Sandy Bridge]
#define	SandyBridge			1
#define	Sandy_1G_CPUID_SIGNATURE	{ExtFamily:0x0, Family:0x6, ExtModel:0x2, Model:0xD}
#define	Sandy_2G_CPUID_SIGNATURE	{ExtFamily:0x0, Family:0x6, ExtModel:0x2, Model:0xA}
#define	Sandy_BASE_CLOCK		100
//	[Ivy Bridge]
#define	IvyBridge			2
#define	Ivy_CPUID_SIGNATURE		{ExtFamily:0x0, Family:0x6, ExtModel:0x3, Model:0xA}
#define	Ivy_BASE_CLOCK			100
//	[Haswell]
#define	Haswell				3
#define	Haswell_3C_CPUID_SIGNATURE	{ExtFamily:0x0, Family:0x6, ExtModel:0x3, Model:0xC}
#define	Haswell_45_CPUID_SIGNATURE	{ExtFamily:0x0, Family:0x6, ExtModel:0x4, Model:0x5}
#define	Haswell_46_CPUID_SIGNATURE	{ExtFamily:0x0, Family:0x6, ExtModel:0x4, Model:0x6}
#define	Haswell_BASE_CLOCK		100

#define	LOOP_MIN_MS	10
#define LOOP_MAX_MS	500
#define	LOOP_DEF_MS	100

typedef struct
{
	struct
	{
		unsigned char Chr[4];
	} AX, BX, CX, DX;
} BRAND;

typedef struct
{
	struct
	{
		struct SIGNATURE
		{
		unsigned int
			Stepping	:  4-0,
			Model		:  8-4,
			Family		: 12-8,
			ProcType	: 14-12,
			Unused1		: 16-14,
			ExtModel	: 20-16,
			ExtFamily	: 28-20,
			Unused2		: 32-28;
		} AX;
		struct
		{
		unsigned int
			Brand_Id	:  8-0,
			CLFSH_Size	: 16-8,
			MaxThread	: 24-16,
			APIC_Id		: 32-24;
		} BX;
		struct
		{
		unsigned int
			SSE3	:  1-0,
			PCLMULDQ:  2-1,
			DTES64	:  3-2,
			MONITOR	:  4-3,
			DS_CPL	:  5-4,
			VMX	:  6-5,
			SMX	:  7-6,
			EIST	:  8-7,
			TM2	:  9-8,
			SSSE3	: 10-9,
			CNXT_Id	: 11-10,
			Unused1	: 12-11,
			FMA	: 13-12,
			CX16	: 14-13,
			xTPR	: 15-14,
			PDCM	: 16-15,
			Unused2	: 17-16,
			PCID	: 18-17,
			DCA	: 19-18,
			SSE41	: 20-19,
			SSE42	: 21-20,
			x2APIC	: 22-21,
			MOVBE	: 23-22,
			POPCNT	: 24-23,
			TSCDEAD	: 25-24,
			AES	: 26-25,
			XSAVE	: 27-26,
			OSXSAVE	: 28-27,
			AVX	: 29-28,
			F16C	: 30-29,
			RDRAND	: 31-30,
			Unused3	: 32-31;
		} CX;
		struct
		{
		unsigned int
			FPU	:  1-0,
			VME	:  2-1,
			DE	:  3-2,
			PSE	:  4-3,
			TSC	:  5-4,
			MSR	:  6-5,
			PAE	:  7-6,
			MCE	:  8-7,
			CX8	:  9-8,
			APIC	: 10-9,
			Unused1	: 11-10,
			SEP	: 12-11,
			MTRR	: 13-12,
			PGE	: 14-13,
			MCA	: 15-14,
			CMOV	: 16-15,
			PAT	: 17-16,
			PSE36	: 18-17,
			PSN	: 19-18,
			CLFSH	: 20-19,
			Unused2	: 21-20,
			DS	: 22-21,
			ACPI	: 23-22,
			MMX	: 24-23,
			FXSR	: 25-24,
			SSE	: 26-25,
			SSE2	: 27-26,
			SS	: 28-27,
			HTT	: 29-28,
			TM1	: 30-29,
			Unused3	: 31-30,
			PBE	: 32-31;
		} DX;
	} Std;
	unsigned int	ThreadCount;
	unsigned int	LargestExtFunc;
	struct
	{
		struct
		{
			unsigned int
			LAHFSAHF:  1-0,
			Unused1	: 32-1;
		} CX;
		struct
		{
			unsigned int
			Unused1	: 11-0,
			SYSCALL	: 12-11,
			Unused2	: 20-12,
			XD_Bit	: 21-20,
			Unused3	: 26-21,
			PG_1GB	: 27-26,
			RDTSCP	: 28-27,
			Unused4	: 29-28,
			IA64	: 30-29,
			Unused5	: 32-30;
		} DX;
	} Ext;
	char		BrandString[48+1];
} FEATURES;

typedef struct
{
	union
	{
		struct
		{
			unsigned int
				Ratio		: 16-0,
				ReservedBits	: 32-16;
		};
			unsigned int Lo		: 32-0;
	};
			unsigned int Hi		: 32-0;
} PERF_STATUS;

typedef struct
{
	union
	{
		struct
		{
			unsigned int
				ReservedBits1l	:  8-0,
				MaxNonTurboRatio: 16-8,
				ReservedBits2l	: 28-16,
				Ratio_Limited	: 29-28,
				TDC_TDP_Limited	: 30-29,
				ReservedBits3l	: 32-30;
		};
			unsigned int Lo		: 32-0;
	};
	union
	{
		struct
		{
			unsigned int
				ReservedBits1h	: 10-0, //40-30,
				MinimumRatio	: 18-10,//48-40,
				ReservedBits2h	: 32-18;//64-48;
		};
			unsigned int Hi		: 32-0;
	};
} PLATFORM;

typedef struct {
	union
	{
		struct
		{
			unsigned int
				MaxRatio_1C	:  8-0,
				MaxRatio_2C	: 16-8,
				MaxRatio_3C	: 24-16,
				MaxRatio_4C	: 32-24;
		};
			unsigned int Lo		: 32-0;
	};
			unsigned int Hi		: 32-0;
} TURBO;

typedef struct {
	union
	{
		struct
		{
			unsigned int
				EN_PMC0		:  1-0,
				EN_PMC1		:  2-1,
				EN_PMC2		:  3-2,
				EN_PMC3		:  4-3,
				ReservedBits1	: 32-4;
		};
			unsigned int Lo		: 32-0;
	};
	union
	{
		struct
		{
			unsigned int
				EN_FIXED_CTR0	:  1-0,//33-32,
				EN_FIXED_CTR1	:  2-1,//34-33,
				EN_FIXED_CTR2	:  3-2,//35-34,
				ReservedBits2	: 32-3;//64-35;
		};
			unsigned int Hi		: 32-0;
	};
} GLOBAL_PERF_COUNTER;

typedef struct
{
	union
	{
		struct
		{
			unsigned int
				EN0_OS		:  1-0,
				EN0_Usr		:  2-1,
				AnyThread_EN0	:  3-2,
				EN0_PMI		:  4-3,
				EN1_OS		:  5-4,
				EN1_Usr		:  6-5,
				AnyThread_EN1	:  7-6,
				EN1_PMI		:  8-7,
				EN2_OS		:  9-8,
				EN2_Usr		: 10-9,
				AnyThread_EN2	: 11-10,
				EN2_PMI		: 12-11,
				ReservedBits	: 32-12;
		};
			unsigned int Lo		: 32-0;
	};
			unsigned int Hi		: 32-0;
} FIXED_PERF_COUNTER;

typedef struct
{
	union
	{
		struct
		{
			unsigned int
				StatusBit       :  1-0,
				StatusLog       :  2-1,
				PROCHOT         :  3-2,
				PROCHOTLog      :  4-3,
				CriticalTemp    :  5-4,
				CriticalTempLog :  6-5,
				Threshold1      :  7-6,
				Threshold1Log   :  8-7,
				Threshold2      :  9-8,
				Threshold2Log   : 10-9,
				PowerLimit      : 11-10,
				PowerLimitLog   : 12-11,
				ReservedBits1   : 16-12,
				DTS             : 23-16,
				ReservedBits2   : 27-23,
				Resolution      : 31-27,
				ReadingValid    : 32-31;
		};
			unsigned int Lo		: 32-0;
	};
			unsigned int Hi		: 32-0;
} THERM_STATUS;

typedef struct
{
	union
	{
		struct
		{
			unsigned int
				ReservedBits1   : 16-0,
				Target          : 24-16,
				ReservedBits2   : 32-24;
		};
			unsigned int Lo		: 32-0;
	};
			unsigned int Hi		: 32-0;
} TJMAX;
/*
typedef struct
{
	int			FD;
	unsigned long long	ThreadCount,
				ClockSpeed;
} BIOS;
*/
typedef struct
{
	unsigned int		cpu;
	struct task_struct	*TID;

	GLOBAL_PERF_COUNTER	GlobalPerfCounter;
	FIXED_PERF_COUNTER	FixedPerfCounter;
	PERF_STATUS		Operating;

	unsigned long long	UnhaltedCoreCycles[2],
				UnhaltedRefCycles[2],
				UnhaltedRatio,
				UnhaltedFreq;
	struct {
		unsigned long long
				C3[2],
				C6[2];
	} RefCycles;
	struct {
		double		C0,
				C1,
				C3,
				C6;
	} State;
	unsigned long long	TSC[2],
				DeltaTSC;

	TJMAX			TjMax;
	THERM_STATUS		Therm;
	unsigned long long	Temp;
} CORE;

typedef struct
{
	unsigned int		idleTime;
	int			ArchID;
	FEATURES		Features;
	PLATFORM		Platform;
	TURBO			Turbo;
//	BIOS			Bios;
	CORE			Core[_MAX_CPU_];
} PROCESSOR;
